package com.github.caijh.mall.wechatMessage.service.impl;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;

import com.alibaba.fastjson.JSON;
import com.github.caijh.commons.util.DateUtils;
import com.github.caijh.commons.util.Maps;
import com.github.caijh.framework.data.redis.Redis;
import com.github.caijh.framework.log.util.LogUtils;
import com.github.caijh.framework.util.XmlUtils;
import com.github.caijh.mall.article.model.Article;
import com.github.caijh.mall.article.service.ArticleService;
import com.github.caijh.mall.constants.WeChatConstants;
import com.github.caijh.mall.system.service.SystemAttachmentService;
import com.github.caijh.mall.user.service.UserTokenService;
import com.github.caijh.mall.wechat.model.WechatReply;
import com.github.caijh.mall.wechat.service.WechatReplyService;
import com.github.caijh.mall.wechatMessage.service.WeChatMessageService;
import com.github.caijh.mall.wechatMessage.vo.MessageImageItemVo;
import com.github.caijh.mall.wechatMessage.vo.MessageImageVo;
import com.github.caijh.mall.wechatMessage.vo.MessageReplyDataVo;
import com.github.caijh.mall.wechatMessage.vo.MessageTextVo;
import com.github.caijh.mall.wechatMessage.vo.MessageVoiceItemVo;
import com.github.caijh.mall.wechatMessage.vo.MessageVoiceVo;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;


@Data
@Service
public class WeChatMessageServiceImpl implements WeChatMessageService {

    private static final Logger logger = LogUtils.getLogger(WeChatMessageServiceImpl.class);

    @Inject
    private Redis redis;

    @Autowired
    private WechatReplyService wechatReplyService;

    @Autowired
    private ArticleService articleService;

    @Autowired
    private UserTokenService userTokenService;

    @Autowired
    private SystemAttachmentService systemAttachmentService;

    //接收人，被动回复消息的时候为发送人
    private String toUserName;

    //发送人，被动回复消息的时候为接收人
    private String fromUserName;

    //接收消息类型
    private String msgType;

    //接收消息内容
    private String content;

    //消息事件
    private String event;

    //事件key
    private String eventKey;

    //关键字回复对象
    private WechatReply wechatReply;


    /**
     * 处理微信推送过来的消息，并且组装成需要发送的数据，二次处理
     *
     * @param request HttpServletRequest request请求
     * @return String
     * @author Mr.Zhang
     * @since 2020-06-03
     */
    @Override
    public String init(HttpServletRequest request) {
        Map<String, Object> map = null;
        try {
            map = Maps.fromXml(StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8));
        } catch (IOException e) {
            e.printStackTrace();
        }

        setToUserName(((String) map.get("ToUserName")));
        setFromUserName(((String) map.get("FromUserName")));
        setMsgType(((String) map.getOrDefault("MsgType", "text"))); //如果没有类型，则按默认处理
        setContent(((String) map.getOrDefault("Content", "default"))); //如果没有内容，则按默认处理
        setEvent(((String) map.getOrDefault("Event", "")));
        setEventKey(((String) map.getOrDefault("EventKey", "")));


        //处理内容
        getReplyByContent();

        if (null == getWechatReply()) {
            return "";
        }

        //设置需要回复的内容
        String response = setXml();

        logger.info("微信被动回复消息 {}", response);
        return response;
    }

    /**
     * 匹配关键字并且组装xml数据
     *
     * @return String
     * @author Mr.Zhang
     * @since 2020-06-03
     */
    private String setXml() {
        if (StringUtils.isBlank(getWechatReply().getType())) {
            return "";
        }
        String type = getWechatReply().getType().toLowerCase();
        MessageReplyDataVo messageReplyDataVo = JSON.toJavaObject(JSON.parseObject(wechatReply.getData()), MessageReplyDataVo.class);

        switch (type) {
            case WeChatConstants.WE_CHAT_MESSAGE_RESP_MESSAGE_TYPE_TEXT:
                MessageTextVo messageTextVo = new MessageTextVo(getFromUserName(), getToUserName(), messageReplyDataVo.getContent());
                return XmlUtils.toXml(messageTextVo, "xml");
            case WeChatConstants.WE_CHAT_MESSAGE_RESP_MESSAGE_TYPE_VOICE:
                return XmlUtils.toXml(new MessageVoiceVo(getFromUserName(), getToUserName(), new MessageVoiceItemVo(messageReplyDataVo.getMediaId())), "xml");
            case WeChatConstants.WE_CHAT_MESSAGE_RESP_MESSAGE_TYPE_IMAGE:
                return XmlUtils.toXml(new MessageImageVo(getFromUserName(), getToUserName(), new MessageImageItemVo(messageReplyDataVo.getMediaId())), "xml");
            case WeChatConstants.WE_CHAT_MESSAGE_RESP_MESSAGE_TYPE_NEWS:
                //文章
                return getNews(messageReplyDataVo.getArticleId());
            default:
                return "";
        }
    }

    /**
     * 组装文章消息
     *
     * @param articleId Integer 文章id
     * @return MessageVoiceVo
     * @author Mr.Zhang
     * @since 2020-06-03
     */
    private String getNews(Integer articleId) {
        Article article = articleService.getById(articleId);
        if (null == article || article.getStatus() || article.getHide()) {
            return "";
        }

        return "<xml>\n"
                + "  <ToUserName><![CDATA[" + fromUserName + "]]></ToUserName>\n"
                +
                "  <FromUserName><![CDATA[" + toUserName + "]]></FromUserName>\n"
                +
                "  <CreateTime>" + ((int) DateUtils.currentTimestamp()) + "</CreateTime>\n"
                +
                "  <MsgType><![CDATA[news]]></MsgType>\n"
                +
                "  <ArticleCount>1</ArticleCount>\n"
                +
                "  <Articles>\n"
                +
                "    <item>\n"
                +
                "      <Title><![CDATA[" + article.getTitle() + "]]></Title>\n"
                +
                "      <Description><![CDATA[" + article.getShareSynopsis() + "]]></Description>\n"
                +
                "      <PicUrl><![CDATA[" + article.getImageInput() + "]]></PicUrl>\n"
                +
                "      <Url><![CDATA[" + article.getUrl() + "]]></Url>\n"
                +
                "    </item>\n"
                +
                "  </Articles>\n"
                +
                "</xml>\n";
    }


    /**
     * 处理不同的消息类型
     *
     * @author Mr.Zhang
     * @since 2020-06-03
     */
    private void getReplyByContent() {
        WechatReply wp = new WechatReply();
        switch (getMsgType()) {
            case WeChatConstants.WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_EVENT:
                if (StringUtils.isBlank(getEvent())) {
                    break;
                }
                switch (getEvent().toLowerCase()) {
                    case WeChatConstants.WE_CHAT_MESSAGE_EVENT_TYPE_UNSUBSCRIBE:
                    case WeChatConstants.WE_CHAT_MESSAGE_EVENT_TYPE_SCAN:
                    case WeChatConstants.WE_CHAT_MESSAGE_EVENT_TYPE_LOCATION:
                    case WeChatConstants.WE_CHAT_MESSAGE_EVENT_TYPE_VIEW:
                        //暂时不处理
                        break;
                    case WeChatConstants.WE_CHAT_MESSAGE_EVENT_TYPE_SUBSCRIBE:
                        wp = wechatReplyService.getVoByKeywords(WeChatConstants.WE_CHAT_MESSAGE_EVENT_TYPE_SUBSCRIBE.toLowerCase());
                        break;
                    case WeChatConstants.WE_CHAT_MESSAGE_EVENT_TYPE_CLICK:
                        wp = wechatReplyService.getVoByKeywords(eventKey);
                        break;
                    default:
                        break;
                }
                break;
            case WeChatConstants.WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_TEXT:
                wp = wechatReplyService.getVoByKeywords(getContent());
                break;
            case WeChatConstants.WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_IMAGE:
            case WeChatConstants.WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_VOICE:
            case WeChatConstants.WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_VIDEO:
            case WeChatConstants.WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_LOCATION:
            case WeChatConstants.WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_LINK:
                //不需要处理
                break;
            default:
                break;
        }

        if (null == wp) {
            //无效关键字回复
            wp = wechatReplyService.getVoByKeywords(WeChatConstants.WE_CHAT_MESSAGE_DEFAULT_CONTENT_KEY);
        }
        setWechatReply(wp);
    }

}
